/**
 * @file	LaneAgent.h
 *
 * @brief	Declares the lane agent class.
 */

#pragma once

#ifndef LANEAGENT_H_
#define LANEAGENT_H_

#include "Agent.h"
#include "Lane.h"
#include "Nest.h"
#include "Feeder.h"

class Lane;
class Nest;
class Feeder;

/**
 * @class	LaneAgent
 *
 * @brief	Lane agent.
 *
 * @author	Nathan Perry
 */

class LaneAgent : public Agent, public Lane 
{
	private:

	//Timer to tell the nest when it should be full

	/**
	 * @class	CallNestTimer
	 *
	 * @brief	Call nest timer.
	 *
	 * @author	Nathan Perry
	 */

	class CallNestTimer : public Thread {
	public:
		CallNestTimer() {}
		CallNestTimer(LaneAgent* la) {
			myLane = la;
		}
		~CallNestTimer();
		virtual void run() {
			sleep(((myLane->getGUI()->Length*(myLane->factorySpeed))/myLane->laneSpeed)/100);
			myLane->tellNestItIsFull();
			stop();
		}
	private:
		LaneAgent* myLane;
	};

	//Timer to stop the Nest Purging

	/**
	 * @class	PurgeStopTimer
	 *
	 * @brief	Purge stop timer.
	 *
	 * @author	Nathan Perry
	 */

	class PurgeStopTimer : public Thread {
	public:
		PurgeStopTimer() {}
		PurgeStopTimer(LaneAgent* la) {
			myLane = la;
		}
		~PurgeStopTimer();
		virtual void run() {
			sleep(((myLane->getGUI()->Length*(myLane->factorySpeed))/myLane->laneSpeed)/100);
			myLane->informPurgingComplete();
			stop();
		}
	private:
		LaneAgent* myLane;
	};

	GUILaneInterface* guiLane;
	Feeder* feeder;
	Nest* nest;

	public:

	bool testing;
	enum LaneState {Purge, None, Request_More_Parts, Speed_Changed};
	float laneSpeed;
	float factorySpeed;
	LaneState state;
	PartType partType;
	CallNestTimer* cnTimer;
	PurgeStopTimer* psTimer;

	//Constructors
	LaneAgent(std::string name);
	
	//Assessors
	void changeSpeed(float newSpeed);
	void setGUI(GUILaneInterface* gui);
	void setFeeder(Feeder* feederAgent);
	void setNest(Nest* nestAgent);
	void setFactorySpeed(float newSpeed);
	int getSpeed();
	GUILane* getGUI();

	//Messages
	//From Nest
	virtual void msgPleaseGetParts(PartType p);
	//From Feeder
	virtual void msgHereAreParts(PartType p);
	//From Elsewhere
	virtual void msgYourSpeedNeedsToChange(int speed);
	//Schedule
	virtual bool pickAndExecuteAnAction();

	//Actions
	//To Nest
	void tellNestItIsFull();
	//To Nest
	void informPurgingComplete();
	//To Feeder
	void returnPartTypeToFeeder();
	//To Self
	void purgeLaneOfParts();
	//To GUI
	void tellGUIToStart();
	//To GUI
	void tellGUISpeedChanged();
	//To GUI
	void tellGUIToStop();
	void handleBreak();
	void handleFix();
};

#endif